﻿// Copyright 2008 Chris Varley (http://www.contractdriven.net/)
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//    http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

using ContractDriven;

namespace ContractDrivenTests
{
	class TestContractBoundClass : ContractBoundObject
	{
		private string _string;
		private int _int;

		/// <summary>
		/// A test class that implements 2 properties with Contract Constraints
		/// MyString - Can be any string that does not equal string.Empty
		/// MyInt - Can be any int between 50 and 100
		/// </summary>
        public TestContractBoundClass(string defaultString, int defaultIntValue)
        {
			_string = defaultString;
			_int = defaultIntValue;

			Invariant(() => Assert.IsNotNullOrEmpty(_string));
			Invariant(()=> Assert.IsInRange(_int, 50, 100));
        }

		/// <summary>
		/// Used for "Assign" test. Internal Invariant... Must not be null or empty.
		/// Value assigned using Contract.Assign before invariants are processed on method exit.
		/// </summary>
		public string MyString
		{
			get { return _string; }
			set
			{
				Contract.Assign(this, ref _string, value);
			}
		}

		/// <summary>
		/// Used for "Invariant" Test. Internal Invariant must be between 50 and 100.
		/// Value assigned in standard way, so invariants are evaluated on method exit.
		/// </summary>
		public int MyInt
		{
			get { return _int; }
			set
			{
				_int = value;
			}
		}


		/// <summary>
		/// Used for "Require" Test
		/// </summary>
		/// <param name="value"></param>
		public void SetMyString_Require_StringLength_10(string value)
		{
			Require(value.Length == 10, "String should be exactly 10 character long.");
			_string = value;
		}


		/// <summary>
		/// Used for "Ensure" Test
		/// </summary>
		public void Increment_MyInt_Ensure_DoesNotExceed_70(int value)
		{
			_int =  value + 1;
			Ensure(_int <= 70, "_int should be less than or equal to 70");
		}

		/// <summary>
		/// Used for "Track" Test
		/// </summary>
		public void Increment_MyInt_Ensure_NoSideEffects(int value)
		{
			//track value
			var key = Track(value);

			//increment it
			value += 1;
			_int = value;
 				
			//do something else here that may alter value; 
			//ensure that it has not been changed by some loop or something in the 
			Ensure(value == (int)Before(key) + 1);

		}



	}
}
